#pragma once

#include "containers.h"
#include "types.h"
#include <cstring>
#include <ctime>

namespace Trade {

enum class OPPUT_DIFF_TYPE : uint8_t
{
  UNKNOW,
  SAME,
  SMALL,
  LARGE,
};

struct Opportunity
{
  percent_t trend_up = 0;
  percent_t trend_dn = 0;
  percent_t force_up = 0;
  percent_t force_dn = 0;
  percent_t vision_up = 0;
  percent_t vision_dn = 0;
  percent_t oppor_up = 0;
  percent_t oppor_dn = 0;

  void print() const noexcept;
  dir_t get_oppor_dir() const noexcept;
  percent_t get_cur_percent() const noexcept;
  dir_t get_virutal_dir() const noexcept;
  dir_t get_trend_dir() const noexcept;
  dir_t get_force_dir() const noexcept;
  dir_t get_stable_dir() const noexcept;
  percent_t get_stable_percent() const noexcept;
  OPPUT_DIFF_TYPE get_opportunity_difference() const noexcept;
  OPPUT_DIFF_TYPE get_virutal_difference() const noexcept;
  OPPUT_DIFF_TYPE get_trend_difference() const noexcept;
  OPPUT_DIFF_TYPE get_force_difference() const noexcept;
  bool good() const noexcept;
  bool operator!=(const Opportunity& o) const noexcept
  {
    return memcmp((void*)(this), &o, sizeof(Opportunity));
  }
};

struct OppurtunityDir
{
  dir_t dir_op = 0;
  percent_t up = 0;
  percent_t dn = 0;
  time_t tm = 0;
  price_t hp = 0;
};

struct BigO
{
  dir_t dir = 0;
  dir_t d_local = 0;
  percent_t percent = 0;
  time_t tm = 0;
  int64_t idx = 0;
  price_t hpx = 0;
  price_t delta = 0;

  void print(const price_t hpx, const time_t ts) const noexcept
  {
    printf("%d %d%% | %d mins %.02lf\n",
           dir,
           percent,
           int((ts - tm) / 60),
           hpx - this->hpx);
  }
};

using BigOpporRecord = CircleVector<BigO, 200>;

struct OppurReverse
{
  dir_t r_dir = 0;
  percent_t oppor = 0;
  price_t ex_space = 0;
};

using BigOppor10 = DataArray<BigO, 10>;

struct Oppor
{
  dir_t dir_oppor = 0;
  percent_t pct_oppor = 0;
  percent_t pct_min = 0;
  percent_t pct_max = 0;
  time_t tm_min = 0;
  time_t tm_max = 0;
  price_t hpx_max = 0;
  price_t hpx_min = 0;

  void print(const price_t hpx, const time_t ts) const noexcept {
        printf("%d %d | %d%% ~ %d%% | %d ~ %d mins %.02lf ~ %.02lf\n",
           dir_oppor,
           pct_oppor,
           pct_max,
           pct_min,
           int((ts - tm_min) / 60),
           int((ts - tm_max) / 60),
           hpx - this->hpx_max,
           hpx - this->hpx_min);

  }
};
using OpporVector = CircleVector<Oppor, 1000>;

struct OpportunitySeries
{
  dir_t add_new_opportunity(const dir_t d,
                            const percent_t pct,
                            const time_t tm,
                            const price_t hpx) noexcept;
  dir_t large_oppor(const time_t tm, const price_t hpx) const noexcept;
  OpporVector ov;
};

using Oppor10 = DataArray<Oppor, 10>;

} // namespace Trade